<?php

/**
* manipulator for physical path node
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 2006-01-26 15:06:29
*/
class pathNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	* use pathNode::getNode to get an appropriate instance
	* @access private
	* /
	function pathNode($path) {
		$this->__construct($path);
	}/**/
	
	/**
	* "real" constructor.
	* use parent::__construct in subclasses to call parent constructor
	* @access public
	*/
	protected function __construct($path) {
		$this->setInfo($path);
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* returns appropriate instance of pathNode or pathNode subclass
	* @static
	* @param string $path
	* @access public
	* @return pathNode|folderNode|fileNode etc
	*/
	public function & getNode($path) {
		$n=NULL;
		// getting path node heritage class list by specifity desc
		$classes=pathNode::heritage();
		foreach ($classes as $class) {
			//$detection=$class::selfDetector($path)
			$detection=call_user_func(array(&$class, "selfDetector"),$path);
			if ($detection) {
				// echo "<br />detected $class for $path ! ";
				$n=&new $class($path);
				return $n;
			}
		}
		if (is_null($n)) {
			trigger_error("pathnode::getnode(): no pathnode class found for $path");
		}
		return $n;
	}/**/
	
	/**
	* retrieve all subclasses and edventually declare a new subclass
	* If $class is provided, add a subclass to 
	* @param string $class
	* @param int $specificity 01-99, default 20 higher specificity override more generic classes
	* @access public
	* @static
	* @return array classes name with keys sheme specificity-classname, sorted on keys desc
	*/
	public static function heritage($class=NULL,$specificity=20) {
		static $classes;
		// basic classes
		$classes['01-pathnode']='pathnode';
		//$classes['02-filenode']='filenode';
		//$classes['02-foldernode']='foldernode';
		// adding subclass
		if (is_string($class) and is_int($specificity) and !in_array($class,$classes)) {
			$specificity=sprintf('%02d',$specificity);
			$class=strtolower($class);
			$classes["$specificity-$class"]=$class;
		}
		// sorting by specificity desc
		krsort($classes);
		return $classes;
	}/**/
	
	/**
	* sets a reference to parent node
	* @param pathNode &$node
	* @access public
	* @return bool
	*/
	public function setParent(&$node) {
		if (!is_a($node,'pathnode')) return false;
		$this->_parent=&$node;
		return true;
	}/**/

	/**
	* 
	* @access public
	* @return string basename
	*/
	public function getBaseName() {
		return $this->basename;
	}/**/
	
	/**
	* returns path from the main script directory
	* @param
	* @access public
	* @return string
	*/
	public function getRelativePath() {
		return $this->relative_path;
	}/**/
	
	/**
	* alias for getrelative path
	* @param
	* @access public
	* @return string
	*/
	public function getPath() {
		return $this->getRelativePath();
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	//var $pathInfo; // information array about path
	//var $type='path';
	protected $_parent;
	protected $exists;
	protected $basename;
	protected $path; // full path
	protected $relative_path; // path from current main script
	protected $absolute_path; // path from server root
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* detects if path applies to self class.
	* subclasses HAVE to implement this method
	* @param
	* @access protected
	* @return bool
	*/
	protected function selfDetector($path) {
		return false;
	}/**/

	/**
	* sets main path information properties from path
	* @param string $path
	* @access protected
	* @return bool
	*/
	protected function setInfo($path) {
		// translating windows path to standard ones
		$path=str_replace('\\','/',$path);
		$this->path=$path;
		$realpath=realpath($path);
		// a dirty hack for some web hosts using absolute paths
		if (PHP_OS!='WINNT' and substr($realpath,0,1)!='/')
			$realpath='/'.$realpath;
		$this->exists=file_exists($realpath);
		$parts=pathinfo($realpath);
		$this->basename=$parts['basename'];
		$this->absolute_path=$realpath;
		// getting relative path by substracting main script's dirname from absolute path
		//$base_path=
		$this->relative_path=substr($realpath
			,strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1);
		// translating windows paths to standard ones
		//$this->path=str_replace('\\','/',$this->path);
		//$this->relative_path=str_replace('\\','/',$this->relative_path);
		return true;
	}/**/

	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}
?>
